﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Engine.Dtd.Schema;

namespace Engine.Sgml {
    /// <summary>
    /// Represents an SGML attribute.
    /// </summary>
    [DebuggerDisplay("{Name}={Value}")]
    public sealed partial class SAttribute : SObject {
        internal static bool NamespaceReserved(string ns) {
            if (string.Equals("http://www.w3.org/2000/xmlns/", ns, StringComparison.Ordinal))
                return false;
            if (ns == null)
                return false;
            else
                return true;
            }

        /// <summary>
        /// Initialize a new instance of the SAttribute class.
        /// </summary>
        internal SAttribute() {
            Name = SName.Empty;
            NodeType = SgmlNodeType.Attribute;
            }

        /// <summary>
        /// Initialize a new instance of the SAttribute class with specified name.
        /// </summary>
        /// <param name="name">A string that represents the name</param>
        /// <param name="value">A string that represents the value of attribute.</param>
        /// <exception cref="System.ArgumentNullException">If a <paramref name="name"/> <paramref name="value"/> is null.</exception>
        public SAttribute(SName name, string value) {
            Guard.ArgumentNotNull(name, "name");
            Guard.ArgumentNotNull(value, "value");
            Name = name;
            Value = value;
            NodeType = SgmlNodeType.Attribute;
            }

        /// <summary>
        /// Creates a duplicate of this attribute.
        /// </summary>
        /// <returns>The cloned attribute.</returns>
        public SAttribute Clone() {
            SAttribute clone = new SAttribute();
            clone.CopyFrom(this);
            clone.Declaration = Declaration;
            return clone;
            }

        /// <summary>
        /// Gets the DTD declaration of this attribute.
        /// </summary>
        public DAttribute Declaration { get; internal set; }

        internal void Reset(string name) {
            Clear();
            Name = SName.Get(name);
            }

        internal override void Clear() {
            base.Clear();
            Declaration = null;
            }

        /// <summary>
        /// Convers a SAttribute to a string object.
        /// </summary>
        /// <param name="attribute">A SAttribute object.</param>
        /// <returns>A string that represent a value of this attribute, or null if the specified attribute is null.</returns>
        public static implicit operator string(SAttribute attribute) {
            if (attribute == null)
                return null;
            else
                return attribute.Value;
            }

        internal void InitializeDeclaration(DtdSchema schema, bool caseSensitiveTags) {
            Debug.Assert(Parent != null);
            Debug.Assert(schema != null);
            if (Parent.HasDeclaration && Parent.Declaration.HasAttributes) {
                DName = schema.Names[LocalName, caseSensitiveTags];
                if (DName != null)
                    foreach (DAttribute declaration in Parent.Declaration.Attributes) {
                        if (declaration.Name == DName) {
                            Declaration = declaration;
                            break;
                            }
                        }
                }
            }
        }
    }
